home *** CD-ROM | disk | FTP | other *** search
/ Ultra Pack / UltraComputing Partner Applications.iso / SunLabs / tclTK / src / tk4.0 / tkBitmap.c < prev    next >
C/C++ Source or Header  |  1995-05-28  |  16KB  |  552 lines

  1. /* 
  2.  * tkBitmap.c --
  3.  *
  4.  *    This file maintains a database of read-only bitmaps for the Tk
  5.  *    toolkit.  This allows bitmaps to be shared between widgets and
  6.  *    also avoids interactions with the X server.
  7.  *
  8.  * Copyright (c) 1990-1994 The Regents of the University of California.
  9.  * Copyright (c) 1994 Sun Microsystems, Inc.
  10.  *
  11.  * See the file "license.terms" for information on usage and redistribution
  12.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  13.  */
  14.  
  15. static char sccsid[] = "@(#) tkBitmap.c 1.31 95/05/28 14:02:31";
  16.  
  17. #include "tkPort.h"
  18. #include "tk.h"
  19.  
  20. /*
  21.  * The includes below are for pre-defined bitmaps.
  22.  */
  23.  
  24. #include "bitmaps/error"
  25. #include "bitmaps/gray25"
  26. #include "bitmaps/gray50"
  27. #include "bitmaps/hourglass"
  28. #include "bitmaps/info"
  29. #include "bitmaps/questhead"
  30. #include "bitmaps/question"
  31. #include "bitmaps/warning"
  32.  
  33. /*
  34.  * One of the following data structures exists for each bitmap that is
  35.  * currently in use.  Each structure is indexed with both "idTable" and
  36.  * "nameTable".
  37.  */
  38.  
  39. typedef struct {
  40.     Pixmap bitmap;        /* X identifier for bitmap.  None means this
  41.                  * bitmap was created by Tk_DefineBitmap
  42.                  * and it isn't currently in use. */
  43.     int width, height;        /* Dimensions of bitmap. */
  44.     Display *display;        /* Display for which bitmap is valid. */
  45.     int refCount;        /* Number of active uses of bitmap. */
  46.     Tcl_HashEntry *hashPtr;    /* Entry in nameTable for this structure
  47.                  * (needed when deleting). */
  48. } TkBitmap;
  49.  
  50. /*
  51.  * Hash table to map from a textual description of a bitmap to the
  52.  * TkBitmap record for the bitmap, and key structure used in that
  53.  * hash table:
  54.  */
  55.  
  56. static Tcl_HashTable nameTable;
  57. typedef struct {
  58.     Tk_Uid name;        /* Textual name for desired bitmap. */
  59.     Screen *screen;        /* Screen on which bitmap will be used. */
  60. } NameKey;
  61.  
  62. /*
  63.  * Hash table that maps from <display + bitmap id> to the TkBitmap structure
  64.  * for the bitmap.  This table is used by Tk_FreeBitmap.
  65.  */
  66.  
  67. static Tcl_HashTable idTable;
  68. typedef struct {
  69.     Display *display;        /* Display for which bitmap was allocated. */
  70.     Pixmap pixmap;        /* X identifier for pixmap. */
  71. } IdKey;
  72.  
  73. /*
  74.  * For each call to Tk_DefineBitmap one of the following structures is
  75.  * created to hold information about the bitmap.
  76.  */
  77.  
  78. typedef struct {
  79.     char *source;        /* Bits for bitmap. */
  80.     int width, height;        /* Dimensions of bitmap. */
  81. } PredefBitmap;
  82.  
  83. /*
  84.  * Hash table create by Tk_DefineBitmap to map from a name to a
  85.  * collection of in-core data about a bitmap.  The table is
  86.  * indexed by the address of the data for the bitmap, and the entries
  87.  * contain pointers to PredefBitmap structures.
  88.  */
  89.  
  90. static Tcl_HashTable predefTable;
  91.  
  92. /*
  93.  * Hash table used by Tk_GetBitmapFromData to map from a collection
  94.  * of in-core data about a bitmap to a Tk_Uid giving an automatically-
  95.  * generated name for the bitmap:
  96.  */
  97.  
  98. static Tcl_HashTable dataTable;
  99. typedef struct {
  100.     char *source;        /* Bitmap bits. */
  101.     int width, height;        /* Dimensions of bitmap. */
  102. } DataKey;
  103.  
  104. static int initialized = 0;    /* 0 means static structures haven't been
  105.                  * initialized yet. */
  106.  
  107. /*
  108.  * Forward declarations for procedures defined in this file:
  109.  */
  110.  
  111. static void        BitmapInit _ANSI_ARGS_((void));
  112.  
  113. /*
  114.  *----------------------------------------------------------------------
  115.  *
  116.  * Tk_GetBitmap --
  117.  *
  118.  *    Given a string describing a bitmap, locate (or create if necessary)
  119.  *    a bitmap that fits the description.
  120.  *
  121.  * Results:
  122.  *    The return value is the X identifer for the desired bitmap
  123.  *    (i.e. a Pixmap with a single plane), unless string couldn't be
  124.  *    parsed correctly.  In this case, None is returned and an error
  125.  *    message is left in interp->result.  The caller should never
  126.  *    modify the bitmap that is returned, and should eventually call
  127.  *    Tk_FreeBitmap when the bitmap is no longer needed.
  128.  *
  129.  * Side effects:
  130.  *    The bitmap is added to an internal database with a reference count.
  131.  *    For each call to this procedure, there should eventually be a call
  132.  *    to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
  133.  *    aren't needed anymore.
  134.  *
  135.  *----------------------------------------------------------------------
  136.  */
  137.  
  138. Pixmap
  139. Tk_GetBitmap(interp, tkwin, string)
  140.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  141.     Tk_Window tkwin;        /* Window in which bitmap will be used. */
  142.     Tk_Uid string;        /* Description of bitmap.  See manual entry
  143.                  * for details on legal syntax. */
  144. {
  145.     NameKey nameKey;
  146.     IdKey idKey;
  147.     Tcl_HashEntry *nameHashPtr, *idHashPtr, *predefHashPtr;
  148.     register TkBitmap *bitmapPtr;
  149.     PredefBitmap *predefPtr;
  150.     int new;
  151.     Pixmap bitmap;
  152.     int width, height;
  153.     int dummy2;
  154.  
  155.     if (!initialized) {
  156.     BitmapInit();
  157.     }
  158.  
  159.     nameKey.name = string;
  160.     nameKey.screen = Tk_Screen(tkwin);
  161.     nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &nameKey, &new);
  162.     if (!new) {
  163.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr);
  164.     bitmapPtr->refCount++;
  165.     return bitmapPtr->bitmap;
  166.     }
  167.  
  168.     /*
  169.      * No suitable bitmap exists.  Create a new bitmap from the
  170.      * information contained in the string.  If the string starts
  171.      * with "@" then the rest of the string is a file name containing
  172.      * the bitmap.  Otherwise the string must refer to a bitmap
  173.      * defined by a call to Tk_DefineBitmap.
  174.      */
  175.  
  176.     if (*string == '@') {
  177.     Tcl_DString buffer;
  178.     int result;
  179.  
  180.     string = Tcl_TildeSubst(interp, string + 1, &buffer);
  181.     if (string == NULL) {
  182.         goto error;
  183.     }
  184.     result = XReadBitmapFile(Tk_Display(tkwin),
  185.         RootWindowOfScreen(nameKey.screen), string,
  186.         (unsigned int *) &width, (unsigned int *) &height,
  187.         &bitmap, &dummy2, &dummy2);
  188.     Tcl_DStringFree(&buffer);
  189.     if (result != BitmapSuccess) {
  190.         Tcl_AppendResult(interp, "error reading bitmap file \"", string,
  191.             "\"", (char *) NULL);
  192.         goto error;
  193.     }
  194.     } else {
  195.     predefHashPtr = Tcl_FindHashEntry(&predefTable, string);
  196.     if (predefHashPtr == NULL) {
  197.         /*
  198.          * The check for a NULL interpreter is a special hack that
  199.          * allows this procedure to be called from GetShadows in
  200.          * tk3d.c, where it doesn't have an intepreter handle.
  201.          */
  202.  
  203.         if (interp != NULL) {
  204.         Tcl_AppendResult(interp, "bitmap \"", string,
  205.             "\" not defined", (char *) NULL);
  206.         }
  207.         goto error;
  208.     }
  209.     predefPtr = (PredefBitmap *) Tcl_GetHashValue(predefHashPtr);
  210.     width = predefPtr->width;
  211.     height = predefPtr->height;
  212.     bitmap = XCreateBitmapFromData(Tk_Display(tkwin),
  213.         RootWindowOfScreen(nameKey.screen), predefPtr->source,
  214.         (unsigned) width, (unsigned) height);
  215.     }
  216.  
  217.     /*
  218.      * Add information about this bitmap to our database.
  219.      */
  220.  
  221.     bitmapPtr = (TkBitmap *) ckalloc(sizeof(TkBitmap));
  222.     bitmapPtr->bitmap = bitmap;
  223.     bitmapPtr->width = width;
  224.     bitmapPtr->height = height;
  225.     bitmapPtr->display = Tk_Display(tkwin);
  226.     bitmapPtr->refCount = 1;
  227.     bitmapPtr->hashPtr = nameHashPtr;
  228.     idKey.display = bitmapPtr->display;
  229.     idKey.pixmap = bitmap;
  230.     idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey,
  231.         &new);
  232.     if (!new) {
  233.     panic("bitmap already registered in Tk_GetBitmap");
  234.     }
  235.     Tcl_SetHashValue(nameHashPtr, bitmapPtr);
  236.     Tcl_SetHashValue(idHashPtr, bitmapPtr);
  237.     return bitmapPtr->bitmap;
  238.  
  239.     error:
  240.     Tcl_DeleteHashEntry(nameHashPtr);
  241.     return None;
  242. }
  243.  
  244. /*
  245.  *----------------------------------------------------------------------
  246.  *
  247.  * Tk_DefineBitmap --
  248.  *
  249.  *    This procedure associates a textual name with a binary bitmap
  250.  *    description, so that the name may be used to refer to the
  251.  *    bitmap in future calls to Tk_GetBitmap.
  252.  *
  253.  * Results:
  254.  *    A standard Tcl result.  If an error occurs then TCL_ERROR is
  255.  *    returned and a message is left in interp->result.
  256.  *
  257.  * Side effects:
  258.  *    "Name" is entered into the bitmap table and may be used from
  259.  *    here on to refer to the given bitmap.
  260.  *
  261.  *----------------------------------------------------------------------
  262.  */
  263.  
  264. int
  265. Tk_DefineBitmap(interp, name, source, width, height)
  266.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  267.     Tk_Uid name;        /* Name to use for bitmap.  Must not already
  268.                  * be defined as a bitmap. */
  269.     char *source;        /* Address of bits for bitmap. */
  270.     int width;            /* Width of bitmap. */
  271.     int height;            /* Height of bitmap. */
  272. {
  273.     int new;
  274.     Tcl_HashEntry *predefHashPtr;
  275.     PredefBitmap *predefPtr;
  276.  
  277.     if (!initialized) {
  278.     BitmapInit();
  279.     }
  280.  
  281.     predefHashPtr = Tcl_CreateHashEntry(&predefTable, name, &new);
  282.     if (!new) {
  283.         Tcl_AppendResult(interp, "bitmap \"", name,
  284.         "\" is already defined", (char *) NULL);
  285.     return TCL_ERROR;
  286.     }
  287.     predefPtr = (PredefBitmap *) ckalloc(sizeof(PredefBitmap));
  288.     predefPtr->source = source;
  289.     predefPtr->width = width;
  290.     predefPtr->height = height;
  291.     Tcl_SetHashValue(predefHashPtr, predefPtr);
  292.     return TCL_OK;
  293. }
  294.  
  295. /*
  296.  *--------------------------------------------------------------
  297.  *
  298.  * Tk_NameOfBitmap --
  299.  *
  300.  *    Given a bitmap, return a textual string identifying the
  301.  *    bitmap.
  302.  *
  303.  * Results:
  304.  *    The return value is the string name associated with bitmap.
  305.  *
  306.  * Side effects:
  307.  *    None.
  308.  *
  309.  *--------------------------------------------------------------
  310.  */
  311.  
  312. Tk_Uid
  313. Tk_NameOfBitmap(display, bitmap)
  314.     Display *display;            /* Display for which bitmap was
  315.                      * allocated. */
  316.     Pixmap bitmap;            /* Bitmap whose name is wanted. */
  317. {
  318.     IdKey idKey;
  319.     Tcl_HashEntry *idHashPtr;
  320.     TkBitmap *bitmapPtr;
  321.  
  322.     if (!initialized) {
  323.     unknown:
  324.     panic("Tk_NameOfBitmap received unknown bitmap argument");
  325.     }
  326.  
  327.     idKey.display = display;
  328.     idKey.pixmap = bitmap;
  329.     idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
  330.     if (idHashPtr == NULL) {
  331.     goto unknown;
  332.     }
  333.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
  334.     return ((NameKey *) bitmapPtr->hashPtr->key.words)->name;
  335. }
  336.  
  337. /*
  338.  *--------------------------------------------------------------
  339.  *
  340.  * Tk_SizeOfBitmap --
  341.  *
  342.  *    Given a bitmap managed by this module, returns the width
  343.  *    and height of the bitmap.
  344.  *
  345.  * Results:
  346.  *    The words at *widthPtr and *heightPtr are filled in with
  347.  *    the dimenstions of bitmap.
  348.  *
  349.  * Side effects:
  350.  *    If bitmap isn't managed by this module then the procedure
  351.  *    panics..
  352.  *
  353.  *--------------------------------------------------------------
  354.  */
  355.  
  356. void
  357. Tk_SizeOfBitmap(display, bitmap, widthPtr, heightPtr)
  358.     Display *display;            /* Display for which bitmap was
  359.                      * allocated. */
  360.     Pixmap bitmap;            /* Bitmap whose size is wanted. */
  361.     int *widthPtr;            /* Store bitmap width here. */
  362.     int *heightPtr;            /* Store bitmap height here. */
  363. {
  364.     IdKey idKey;
  365.     Tcl_HashEntry *idHashPtr;
  366.     TkBitmap *bitmapPtr;
  367.  
  368.     if (!initialized) {
  369.     unknownBitmap:
  370.     panic("Tk_SizeOfBitmap received unknown bitmap argument");
  371.     }
  372.  
  373.     idKey.display = display;
  374.     idKey.pixmap = bitmap;
  375.     idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
  376.     if (idHashPtr == NULL) {
  377.     goto unknownBitmap;
  378.     }
  379.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
  380.     *widthPtr = bitmapPtr->width;
  381.     *heightPtr = bitmapPtr->height;
  382. }
  383.  
  384. /*
  385.  *----------------------------------------------------------------------
  386.  *
  387.  * Tk_FreeBitmap --
  388.  *
  389.  *    This procedure is called to release a bitmap allocated by
  390.  *    Tk_GetBitmap or TkGetBitmapFromData.
  391.  *
  392.  * Results:
  393.  *    None.
  394.  *
  395.  * Side effects:
  396.  *    The reference count associated with bitmap is decremented, and
  397.  *    it is officially deallocated if no-one is using it anymore.
  398.  *
  399.  *----------------------------------------------------------------------
  400.  */
  401.  
  402. void
  403. Tk_FreeBitmap(display, bitmap)
  404.     Display *display;            /* Display for which bitmap was
  405.                      * allocated. */
  406.     Pixmap bitmap;            /* Bitmap to be released. */
  407. {
  408.     Tcl_HashEntry *idHashPtr;
  409.     register TkBitmap *bitmapPtr;
  410.     IdKey idKey;
  411.  
  412.     if (!initialized) {
  413.     panic("Tk_FreeBitmap called before Tk_GetBitmap");
  414.     }
  415.  
  416.     idKey.display = display;
  417.     idKey.pixmap = bitmap;
  418.     idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
  419.     if (idHashPtr == NULL) {
  420.     panic("Tk_FreeBitmap received unknown bitmap argument");
  421.     }
  422.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
  423.     bitmapPtr->refCount--;
  424.     if (bitmapPtr->refCount == 0) {
  425.     XFreePixmap(bitmapPtr->display, bitmapPtr->bitmap);
  426.     Tk_FreeXId(bitmapPtr->display, (XID) bitmapPtr->bitmap);
  427.     Tcl_DeleteHashEntry(idHashPtr);
  428.     Tcl_DeleteHashEntry(bitmapPtr->hashPtr);
  429.     ckfree((char *) bitmapPtr);
  430.     }
  431. }
  432.  
  433. /*
  434.  *----------------------------------------------------------------------
  435.  *
  436.  * Tk_GetBitmapFromData --
  437.  *
  438.  *    Given a description of the bits for a bitmap, make a bitmap that
  439.  *    has the given properties. *** NOTE:  this procedure is obsolete
  440.  *    and really shouldn't be used anymore. ***
  441.  *
  442.  * Results:
  443.  *    The return value is the X identifer for the desired bitmap
  444.  *    (a one-plane Pixmap), unless it couldn't be created properly.
  445.  *    In this case, None is returned and an error message is left in
  446.  *    interp->result.  The caller should never modify the bitmap that
  447.  *    is returned, and should eventually call Tk_FreeBitmap when the
  448.  *    bitmap is no longer needed.
  449.  *
  450.  * Side effects:
  451.  *    The bitmap is added to an internal database with a reference count.
  452.  *    For each call to this procedure, there should eventually be a call
  453.  *    to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
  454.  *    aren't needed anymore.
  455.  *
  456.  *----------------------------------------------------------------------
  457.  */
  458.  
  459.     /* ARGSUSED */
  460. Pixmap
  461. Tk_GetBitmapFromData(interp, tkwin, source, width, height)
  462.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  463.     Tk_Window tkwin;        /* Window in which bitmap will be used. */
  464.     char *source;        /* Bitmap data for bitmap shape. */
  465.     int width, height;        /* Dimensions of bitmap. */
  466. {
  467.     DataKey nameKey;
  468.     Tcl_HashEntry *dataHashPtr;
  469.     Tk_Uid name = NULL;        /* Initialization need only to prevent
  470.                  * compiler warning. */
  471.     int new;
  472.     static int autoNumber = 0;
  473.     char string[20];
  474.  
  475.     if (!initialized) {
  476.     BitmapInit();
  477.     }
  478.  
  479.     nameKey.source = source;
  480.     nameKey.width = width;
  481.     nameKey.height = height;
  482.     dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &nameKey, &new);
  483.     if (!new) {
  484.     name = (Tk_Uid) Tcl_GetHashValue(dataHashPtr);
  485.     } else {
  486.     autoNumber++;
  487.     sprintf(string, "_tk%d", autoNumber);
  488.     name = Tk_GetUid(string);
  489.     Tcl_SetHashValue(dataHashPtr, name);
  490.     if (Tk_DefineBitmap(interp, name, source, width, height) != TCL_OK) {
  491.         Tcl_DeleteHashEntry(dataHashPtr);
  492.         return TCL_ERROR;
  493.     }
  494.     }
  495.     return Tk_GetBitmap(interp, tkwin, name);
  496. }
  497.  
  498. /*
  499.  *----------------------------------------------------------------------
  500.  *
  501.  * BitmapInit --
  502.  *
  503.  *    Initialize the structures used for bitmap management.
  504.  *
  505.  * Results:
  506.  *    None.
  507.  *
  508.  * Side effects:
  509.  *    Read the code.
  510.  *
  511.  *----------------------------------------------------------------------
  512.  */
  513.  
  514. static void
  515. BitmapInit()
  516. {
  517.     Tcl_Interp *dummy;
  518.  
  519.     dummy = Tcl_CreateInterp();
  520.     initialized = 1;
  521.     Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
  522.     Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int));
  523.     Tcl_InitHashTable(&predefTable, TCL_ONE_WORD_KEYS);
  524.  
  525.     /*
  526.      * The call below is tricky:  can't use sizeof(IdKey) because it
  527.      * gets padded with extra unpredictable bytes on some 64-bit
  528.      * machines.
  529.      */
  530.  
  531.     Tcl_InitHashTable(&idTable, (sizeof(Display *) + sizeof(Pixmap))
  532.         /sizeof(int));
  533.  
  534.     Tk_DefineBitmap(dummy, Tk_GetUid("error"), (char *) error_bits,
  535.         error_width, error_height);
  536.     Tk_DefineBitmap(dummy, Tk_GetUid("gray50"), (char *) gray50_bits,
  537.         gray50_width, gray50_height);
  538.     Tk_DefineBitmap(dummy, Tk_GetUid("gray25"), (char *) gray25_bits,
  539.         gray25_width, gray25_height);
  540.     Tk_DefineBitmap(dummy, Tk_GetUid("hourglass"), (char *) hourglass_bits,
  541.         hourglass_width, hourglass_height);
  542.     Tk_DefineBitmap(dummy, Tk_GetUid("info"), (char *) info_bits,
  543.         info_width, info_height);
  544.     Tk_DefineBitmap(dummy, Tk_GetUid("questhead"), (char *) questhead_bits,
  545.         questhead_width, questhead_height);
  546.     Tk_DefineBitmap(dummy, Tk_GetUid("question"), (char *) question_bits,
  547.         question_width, question_height);
  548.     Tk_DefineBitmap(dummy, Tk_GetUid("warning"), (char *) warning_bits,
  549.         warning_width, warning_height);
  550.     Tcl_DeleteInterp(dummy);
  551. }
  552.